import sys
from pyqtgraph.Qt import QtWidgets, QtCore
import pyqtgraph.opengl as gl
import numpy as np


class AdvancedAircraftFactory:
    @staticmethod
    def get_b2_stealth_mesh():
        """
        生成一个改进版的 B2 隐身轰炸机模型。
        特点：流线型机身、W型锯齿尾部、融合翼身。
        """
        # --- 1. 定义关键顶点坐标 (x, y, z) ---
        # 坐标系: X朝前, Y朝左, Z朝上
        
        # 中轴线上的点
        nose = [1.5, 0.0, 0.0]        # 0: 机头
        cockpit_top = [0.2, 0.0, 0.25]# 1: 驾驶舱顶部隆起
        tail_center = [-0.8, 0.0, 0.05] # 2: 机尾中心
        belly_center = [0.0, 0.0, -0.1] # 3: 机腹中心 (略微下凸)
        
        # 左翼关键点 (Y > 0)
        # 前缘转折点 (Leading Edge Break)
        le_mid = [0.0, 1.2, 0.05]     # 4
        # 翼尖 (Wing Tip)
        wing_tip = [-1.5, 3.5, 0.1]   # 5
        # 后缘锯齿点 (Trailing Edge Zig-Zags) - 制造W型尾
        te_out = [-1.8, 2.0, 0.05]    # 6: 外侧锯齿凹陷
        te_in =  [-1.2, 0.8, 0.05]    # 7: 内侧锯齿凸起

        # --- 2. 镜像生成右翼点 (Y < 0) ---
        # 对应索引 8, 9, 10, 11
        right_points = []
        for p in [le_mid, wing_tip, te_out, te_in]:
            right_points.append([p[0], -p[1], p[2]])
            
        # 合并所有顶点
        # 索引映射:
        # 0:Nose, 1:Top, 2:Tail, 3:Belly
        # 4:L_LE, 5:L_Tip, 6:L_TE_Out, 7:L_TE_In
        # 8:R_LE, 9:R_Tip, 10:R_TE_Out, 11:R_TE_In
        verts = np.array([nose, cockpit_top, tail_center, belly_center, 
                          le_mid, wing_tip, te_out, te_in] + right_points)

        # --- 3. 定义面 (Faces) ---
        # 使用三角形连接顶点。注意逆时针顺序(CCW)通常为正面，但PyQtGraph双面渲染，主要影响光照法线。
        faces = [
            # --- 上表面 (Top Surface) ---
            # 左侧机身与机翼
            [0, 1, 4],    # 机头-座舱-前缘
            [1, 4, 7],    # 座舱-前缘-后缘内
            [1, 7, 2],    # 座舱-后缘内-机尾
            [4, 5, 6],    # 前缘-翼尖-后缘外
            [4, 6, 7],    # 前缘-后缘外-后缘内
            
            # 右侧机身与机翼 (镜像)
            [0, 8, 1],    # 机头-前缘-座舱
            [1, 11, 8],   # 座舱-后缘内-前缘
            [1, 2, 11],   # 座舱-机尾-后缘内
            [8, 10, 9],   # 前缘-后缘外-翼尖
            [8, 11, 10],  # 前缘-后缘内-后缘外

            # --- 下表面 (Bottom Surface / Belly) ---
            # 为了简化，下表面做得比较平坦
            # 左侧
            [0, 4, 3],    # 机头-前缘-机腹
            [3, 4, 7],    # 机腹-前缘-后缘内
            [3, 7, 2],    # 机腹-后缘内-机尾
            [4, 5, 6],    # 前缘-翼尖-后缘外 (下)
            [4, 6, 7],    # 前缘-后缘外-后缘内 (下)
            
            # 右侧
            [0, 3, 8],
            [3, 11, 8],
            [3, 2, 11],
            [8, 9, 10],
            [8, 10, 11]
        ]

        faces = np.array(faces)
        
        # --- 4. 生成 MeshData 并计算法线 ---
        md = gl.MeshData(vertexes=verts, faces=faces)
        return md
    
class B2Visualizer(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("High-Quality B2 Stealth Bomber Model")
        self.resize(1000, 800)
        
        # 1. 设置黑色背景的 View
        self.w = gl.GLViewWidget()
        self.w.setBackgroundColor('k') # 黑色背景
        self.w.setCameraPosition(distance=10, elevation=30, azimuth=45)
        self.setCentralWidget(self.w)
        
        # 2. 添加网格地面 (为了对比)
        g = gl.GLGridItem()
        g.scale(2, 2, 1)
        g.setColor((1, 1, 1, 0.1)) # 很淡的白色网格
        self.w.addItem(g)

        # 3. 获取改进的模型数据
        md = AdvancedAircraftFactory.get_b2_stealth_mesh()

        # --- 展示风格 A: 战术隐身风格 (深灰实体 + 青色线框) ---
        # 这种风格最适合无人机集群监控界面
        self.stealth_drone = gl.GLMeshItem(
            meshdata=md,
            smooth=True,            # 开启平滑，让棱角不那么分明
            shader='shaded',        # 开启光照
            drawEdges=True,         # 画线框
            color=(0.15, 0.15, 0.18, 1.0),  # 机身颜色：深炭灰色
            edgeColor=(0, 1, 1, 1.0)        # 线框颜色：高亮青色 (Cyan)
        )
        # 稍微放大一点，放在左边
        self.stealth_drone.scale(1.5, 1.5, 1.5)
        self.stealth_drone.translate(-4, 0, 2)
        self.w.addItem(self.stealth_drone)

        # --- 展示风格 B: 材质高光风格 (模拟金属/反光漆) ---
        self.shiny_drone = gl.GLMeshItem(
            meshdata=md,
            smooth=True,
            shader='balloon',       # 使用高光 Shader
            drawEdges=False,        # 不画线，只看反光
            color=(0.1, 0.1, 0.1, 1.0), # 近乎黑色
            glOptions='translucent'
        )
        self.shiny_drone.scale(1.5, 1.5, 1.5)
        self.shiny_drone.translate(4, 0, 2)
        self.w.addItem(self.shiny_drone)
        
        # 动画让它们动起来
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update_animation)
        self.timer.start(30)

    def update_animation(self):
        # 简单的旋转展示
        self.stealth_drone.rotate(0.5, 0, 0, 1)
        # 让右边的飞机做俯仰动作
        self.shiny_drone.rotate(0.5, 0, 1, 0)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    win = B2Visualizer()
    win.show()
    sys.exit(app.exec())